package com.mazaiting.redeye.module.user.login

import android.annotation.SuppressLint
import android.text.TextUtils
import cn.jpush.im.android.api.JMessageClient
import cn.jpush.im.api.BasicCallback
import com.mazaiting.easy.base.bean.BaseBean
import com.mazaiting.easy.base.bean.Response
import com.mazaiting.easy.base.mvp.IBaseView
import com.mazaiting.easy.utils.rx.RxScheduler
import com.mazaiting.redeye.module.face.IDetectCallback
import com.mazaiting.face.ui.config.FaceStatusEnum
import com.mazaiting.log.L
import com.mazaiting.redeye.api.FaceApi
import com.mazaiting.redeye.api.UserApi
import com.mazaiting.redeye.base.*
import com.mazaiting.redeye.bean.ResponseDetectImageResultBean
import com.mazaiting.redeye.bean.Request
import com.mazaiting.redeye.bean.ResponseFaceTokenBean
import com.mazaiting.redeye.bean.UserBean
import com.mazaiting.redeye.utils.Rsa
import com.trello.rxlifecycle3.kotlin.bindToLifecycle
import dagger.Component
import io.reactivex.disposables.Disposable
import io.reactivex.functions.Consumer
import javax.inject.Inject

/***
 *
 *
 *                                                    __----~~~~~~~~~~~------___
 *                                   .  .   ~~//====......          __--~ ~~
 *                   -.            \_|//     |||\\  ~~~~~~::::... /~
 *                ___-==_       _-~o~  \/    |||  \\            _/~~-
 *        __---~~~.==~||\=_    -_--~/_-~|-   |\\   \\        _/~
 *    _-~~     .=~    |  \\-_    '-~7  /-   /  ||    \      /
 *  .~       .~       |   \\ -_    /  /-   /   ||      \   /
 * /  ____  /         |     \\ ~-_/  /|- _/   .||       \ /
 * |~~    ~~|--~~~~--_ \     ~==-/   | \~--===~~        .\
 *          '         ~-|      /|    |-~\~~       __--~~
 *                      |-~~-_/ |    |   ~\_   _-~            /\
 *                           /  \     \__   \/~                \__
 *                       _--~ _/ | .-~~____--~-/                  ~~==.
 *                      ((->/~   '.|||' -_|    ~~-/ ,              . _||
 *                                 -_     ~\      ~~---l__i__i__i--~~_/
 *                                 _-~-__   ~)  \--______________--~~
 *                               //.-~~~-~_--~- |-------~~~~~~~~
 *                                      //.-~~~--\
 *                               神兽保佑
 *                              代码无BUG!
 * @author mazaiting
 * @date 2019/5/30
 * @decription
 */
class LoginContract {
    /**
     * 登录视图接口
     */
    interface View : IBaseView, FaceView {
        /**
         * 登录成功
         */
        fun loginSuccess()

        /**
         * 登录失败
         * @param msg 异常信息
         */
        fun loginError(msg: String)
    }

    /**
     * 登录主持人接口
     */
    interface Presenter : ICancelPresenter<View>, FacePresenter {
        /**
         * 登录
         * @param userBean 用户信息
         */
        fun login(userBean: UserBean)

    }

    interface FaceView {
        fun detectSuccess(msg: String)
    }

    interface FacePresenter {
        /**
         * 获取 Access Token
         */
        fun getAccessToken()

        /**
         * 检测策略
         * @param data 二进制数据
         */
        fun detect(data: ByteArray, callback: IDetectCallback)
    }
}

/**
 * 登录主持人
 * @param userApi 用户 api
 */
class LoginPresenter
@Inject constructor(
    // 用户 API
    private val userApi: UserApi,
    // 人脸 API
    private val faceApi: FaceApi
) : BaseCommonPresenter<LoginContract.View>(), LoginContract.Presenter {
    /**
     * Token Disposable
     */
    private var mAccessTokenDispose: Disposable? = null
    /**
     * 检测 Disposable
     */
    private var mDetectDispose: Disposable? = null
    /**
     * 访问令牌
     */
    private var mAccessToken = ""

    override fun getAccessToken() {
        mAccessTokenDispose = faceApi.getAccessToken()
            .compose(RxScheduler.applySchedulers())
            .bindToLifecycle(view.lifecycleProvider)
            .subscribe(object : CustomConsumer<ResponseFaceTokenBean> {
                override fun onSuccess(result: ResponseFaceTokenBean?) {
                    L.d(result.toString())
                    mAccessToken = result?.accessToken.toString()
                }
            }, Consumer { e -> L.d(e.message) })
    }

    override fun detect(data: ByteArray, callback: IDetectCallback) {
        if (!TextUtils.isEmpty(mAccessToken)) {
            mDetectDispose =
                faceApi.detect(mAccessToken, data)
                    .compose(RxScheduler.applySchedulers())
                    .bindToLifecycle(view.lifecycleProvider)
                    .subscribe(object : CustomConsumer<ResponseDetectImageResultBean> {
                        override fun onSuccess(result: ResponseDetectImageResultBean?) {
                            if (null != result) {
                                // 获取人脸列表
                                val faceImageResult = result.result
                                // 判断返回结果是否为空
                                if (null != faceImageResult && faceImageResult.faceNum > 0) {
                                    // 获取人脸列表
                                    val faceList = faceImageResult.faceList
                                    // 检测人脸是否为空
                                    if (faceList.isNotEmpty()) {
                                        // 获取识别出最大的一张脸部信息
                                        val faceImage = faceList[0]
                                        // 获取人脸图像质量
                                        val quality = faceImage.quality
                                        // 人脸各部分遮挡的概率
                                        val occlusion = quality.occlusion
//                                        * left_eye : 0.6, #左眼被遮挡的阈值
//                                        * right_eye : 0.6, #右眼被遮挡的阈值
//                                        * nose : 0.7, #鼻子被遮挡的阈值
//                                        * mouth : 0.7, #嘴巴被遮挡的阈值
//                                        * left_cheek : 0.8, #左脸颊被遮挡的阈值
//                                        * right_cheek : 0.8, #右脸颊被遮挡的阈值
//                                        * chin_contour : 0.6, #下巴被遮挡阈值
                                        var msg = "检测成功"
                                        var status = FaceStatusEnum.OK
                                        when {
                                            occlusion.leftEye > 0.6 -> {
                                                msg = "左眼被遮挡"
                                                status = FaceStatusEnum.OUT_OF_LEFT_MAX_RANGE
                                            }
                                            occlusion.rightEye > 0.6 -> {
                                                msg = "右眼被遮挡"
                                                status = FaceStatusEnum.OUT_OF_RIGHT_MAX_RANGE
                                            }
                                            occlusion.nose > 0.7 -> {
                                                msg = "鼻子被遮挡"
                                                status = FaceStatusEnum.OUT_OF_UP_MAX_RANGE
                                            }
                                            occlusion.mouth > 0.7 -> {
                                                msg = "嘴巴被遮挡"
                                                status = FaceStatusEnum.OUT_OF_DOWN_MAX_RANGE
                                            }
                                            occlusion.leftCheek > 0.8 -> {
                                                msg = "左脸颊被遮挡"
                                                status = FaceStatusEnum.OUT_OF_LEFT_MAX_RANGE
                                            }
                                            occlusion.rightCheek > 0.8 -> {
                                                msg = "右脸被遮挡"
                                                status = FaceStatusEnum.OUT_OF_RIGHT_MAX_RANGE
                                            }
                                            occlusion.nose > 0.6 -> {
                                                msg = "下巴被遮挡"
                                                status = FaceStatusEnum.OUT_OF_DOWN_MAX_RANGE
                                            }
                                            else -> {
                                                msg = "检测成功"
                                                status = FaceStatusEnum.OK
                                            }
                                        }
                                        callback.onDetectCompletion(status, msg)
                                    }
                                }
                            }
                        }
                    }, Consumer { e -> L.d(e.message) })
        } else {
            getAccessToken()
        }
    }

    /**
     * 登录 Disposable
     */
    private var mLoginDispose: Disposable? = null

    override fun login(userBean: UserBean) = if (isNetConnected) {
        // 极光注册用户名
        val jUsername = userBean.username
        // 极光注册密码
        val jPassword = userBean.password
        // 初始化加密工具类
        val rsa = Rsa(getString(Config.KEY_PUBLIC_KEY))
        // 加密密码
        userBean.password = rsa.encrypt(userBean.password)
        view.onShowLoading("登录中...")
        mLoginDispose = userApi.login(userBean)
            .compose(RxScheduler.applySchedulers())
            .bindToLifecycle(view.lifecycleProvider)
            .subscribe(object : CustomConsumer<Response<Request<UserBean>>> {
                override fun onSuccess(result: Response<Request<UserBean>>?)
                        = if (null != result) {
                            if (result.retCode == 1) {
                                jLogin(jUsername, jPassword, result)
                                username = userBean.username
                            } else {
                                view.onShowFailed(result.msg)
                                view.loginError(result.msg)
                            }
                        } else {
                            view.onShowFailed(result?.msg)
                            view.loginError("请求失败")
                        }
            }, Consumer<Throwable> { e ->
//                L.d(e.message)
                e.message?.let { view.loginError(it) }
                view.onShowFailed(e.message)
            })
    } else {
        view.onShowNoNet()
    }

    /**
     * IM 登录
     * @param jUsername 用户名
     * @param jPassword 密码
     */
    private fun jLogin(
        jUsername: String,
        jPassword: String,
        result: Response<Request<UserBean>>
    ) {
        JMessageClient.login(jUsername, jPassword, object : BasicCallback() {
            override fun gotResult(code: Int, msg: String?) {
//                L.d("code: $code, msg: $msg")
                if (code == 0) {
//                    L.d("IM 登录成功")
                    // 请求成功
                    view.onShowSuccess()
                    // 登录成功
                    view.loginSuccess()
                    // 获取 Token
                    token = result.data.token
                    username = jUsername
                } else {
//                    L.d("IM 登录失败")
                    view.onShowFailed(msg)
                    msg?.let { view.loginError("code: $code -- msg: $msg") }
                }
            }
        })
    }

    @SuppressLint("CheckResult")
    fun hello() {
        L.d("hello")
        userApi.hello(token)
            .compose(RxScheduler.applySchedulers())
            .bindToLifecycle(view.lifecycleProvider)
            .subscribe(object : CustomConsumer<BaseBean> {
                override fun onSuccess(result: BaseBean?) {
                    L.d(result.toString())
                }
            }, Consumer<Throwable> { e ->
                L.d(e.message)
            })
    }

    override fun cancel() {
        mLoginDispose?.dispose()
        mAccessTokenDispose?.dispose()
    }

}

/**
 * 登录组件
 */
@Component(dependencies = [ApplicationComponentImpl::class])
interface LoginComponent {
    /**
     * 注入 Activity
     * @param activity 界面
     */
    fun inject(activity: LoginActivity)
}